#include "array.h"
#include <stdio.h>
#include <stdlib.h>

const int BLOCK_SIZE = 20;

Array array_create(int init_size)
{
    Array a;
    a.size = init_size;
    a.array = (int*)malloc(sizeof(int) * a.size);

    return a;
}

void array_free(Array* a)
{
    free(a->array);
    a->array = NULL;
    a->size = 0;
}

// 封装：保护实现细节
int array_size(const Array* a)
{
    return a->size;
}

int* array_at(Array* a, int index)
{
    if (index >= a->size)
    {
        // 如果越界, 就扩展一个BLOCK_SIZE
        array_inflate(a, (index / BLOCK_SIZE + 1) * BLOCK_SIZE - a->size);
    }
    // 返回指针的好处：可以利用返回的指针修改目标位置的值
    // 如果不想返回指针，实现上述用法也可以拆分成以下两个函数
    return &(a->array[index]);
}

// --------------------------------------------
int array_get(const Array* a, int index)
{
    return a->array[index];
}

void array_set(Array* a, int index, int value)
{
    a->array[index] = value;
}
// --------------------------------------------

void array_inflate(Array* a, int more_size)
{
    int* p = (int*)malloc(sizeof(int) * (a->size + more_size));
    // -------------------------------
    // 可以换为 memcpy 函数
    for (int i = 0; i < a->size; i++)
    {
        p[i] = a->array[i];
    }
    // -------------------------------
    free(a->array);
    a->array = p;
    a->size += more_size;
}

int main(int argc, char const *argv[])
{
    Array a = array_create(100);
    printf("%d\n", array_size(&a));

    // 返回指针的好处：可以直接赋值
    *array_at(&a, 0) = 10;
    printf("%d\n", *array_at(&a, 0));
    array_set(&a, 1, 22);
    printf("%d\n", array_get(&a, 1));

    int number;
    int cnt = 0;
    // 无限读入, 不断增长
    while (1)
    {
        // scanf("%d", &array_at(&a, cnt++));
        scanf("%d", &number);
        if (number != -1)
            *array_at(&a, cnt++) = number;
        else break;
    }

    array_free(&a);

    return 0;
}

// 缺陷:
// - 申请新空间时每次复制很低效
// - 总是在申请新空间, 可能导致内存不够分配